﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MiniCPU.Entities
{
    /// <summary>
    /// Bus entity.
    /// </summary>
    public class Bus : DataPropagator
    {
        #region Variables
        /// <summary>
        /// Bus Components collection.
        /// </summary>
        private Dictionary<int, LimitedData> busComponents;

        /// <summary>
        /// Bus selection ports.
        /// </summary>
        private Dictionary<int, ControlPort> busSelect;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Bus"/> class.
        /// </summary>
        /// <param name="numberOfInputs">The number of inputs.</param>
        /// <param name="numberOfBits">The number of bits.</param>
        public Bus(int numberOfInputs, int numberOfBits)
           : base("Bus", 0, numberOfBits)
        {
            this.busComponents = new Dictionary<int, LimitedData>();
            this.busSelect = new Dictionary<int, ControlPort>();
            for (int i = 0; i < numberOfInputs; i++)
            {
                ControlPort port = new ControlPort("Bus Select:" + i.ToString());
                port.DataChanged += new MiniCPU.Events.DataChangedEventHandler(this.Bus_DataChanged);
                this.busSelect.Add(i, port);
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the current bus selection index.
        /// </summary>
        /// <value>The bus selection.</value>
        public int BusSelection
        {
            get
            {
                for (int i = 0; i < this.busSelect.Count; i++)
                {
                    if (this.busSelect[i].Value)
                    {
                        return i;
                    }
                }

                return -1;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Gets the selector.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <returns>The control port.</returns>
        public ControlPort GetSelector(int index)
        {
            return this.busSelect[index];
        }

        /// <summary>
        /// Connects the component.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <param name="component">The component.</param>
        public void ConnectComponent(int position, LimitedData component)
        {
            this.busComponents.Add(position, component);
            component.DataChanged += new MiniCPU.Events.DataChangedEventHandler(this.Bus_DataChanged);
        }

        /// <summary>
        /// Handles the DataChanged event of the bus control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MiniCPU.Events.DataChangedEventArgs"/> instance containing the event data.</param>
        private void Bus_DataChanged(object sender, MiniCPU.Events.DataChangedEventArgs e)
        {
            if (this.BusSelection == -1)
            {
                return;
            }

            UpdateValue(this.busComponents[this.BusSelection].IntValue);
        }
        #endregion
    }
}
